package cn.moonspace.flowerowner.service.impl;

import java.util.ArrayList;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import cn.moonspace.common.util.MyJsonUtil;
import cn.moonspace.flowerowner.entities.Car;
import cn.moonspace.flowerowner.entities.Regulation;
import cn.moonspace.flowerowner.exception.DriverException;
import cn.moonspace.flowerowner.form.DriverForm;
import cn.moonspace.flowerowner.form.RegulationForm;
import cn.moonspace.flowerowner.httpclient.SearchClient;
import cn.moonspace.flowerowner.service.RegulationService;

@Service("regulationService")
public class RegulationServiceImpl extends BaseService implements
		RegulationService {

	@Override
	public JSONObject searchRegulation(RegulationForm regulationForm) throws DriverException {

		// 实时查上海交通违规网，结果解析为json后返回
		JSONObject result;
		try {
			result = SearchClient.searchRegulations(regulationForm.getArea(),
						regulationForm.getCardNo(), regulationForm.getCardType(),
						regulationForm.getMachineNo());
		} catch (Exception e) {
			DriverException de = new DriverException(DriverException.SearchRegulationException, "Search Regulation Error: " + e.getMessage(), this.getClass().getName());
			de.setStackTrace(e.getStackTrace());
			throw de;
		}
		
		Car car = carRepository.findCar(regulationForm.getArea(),
				regulationForm.getCardNo(), regulationForm.getMachineNo(),
				regulationForm.getCardType());
		
		
		if (result.get("error") == null) {
			// 存在违规信息
			// 汽车信息入库
			if (car == null) {
				Car c = new Car();
				c.setCardArea(regulationForm.getArea());
				c.setCardNo(regulationForm.getCardNo());
				c.setCardType(regulationForm.getCardType());
				c.setMachineNo(regulationForm.getMachineNo());
				c.setIsReal(true);
				car = carRepository.save(c);
				log.info("New car : " + car);
			}else{
				//更新车辆真实性为true
				car.setIsReal(true);
				carRepository.save(car);
			}
			// 违规信息入库
			JSONArray array = result.getJSONArray("result");
			for (int i = 0; i < array.size(); i++) {
				JSONObject o = array.getJSONObject(i);
				JSONArray list = o.getJSONArray("list");
				int count = o.getInt("count");
				for (int j = 0; j < count; j++) {
					JSONObject oo = list.getJSONObject(j);
					Regulation rr = regulationRepository.findBySeq(oo.getString("seq"));
					if (rr == null) {
						// 还没有保存该笔违规，是新违规
						Regulation regulation = new Regulation();
						regulation.setSeq(oo.getString("seq"));
						regulation.setTime(oo.getString("time"));
						regulation.setAddress(oo.getString("address"));
						regulation.setDept(oo.getString("dept"));
						regulation.setContent(oo.getString("content"));
						regulation.setRule(oo.getString("rule"));
						regulation.setStatus(oo.getString("status"));

						regulation.setCardArea(regulationForm.getArea());
						regulation.setCardNumber(regulationForm.getCardNo());
						regulation.setCardType(regulationForm.getCardType());

						regulation.setCar(car);
						regulationRepository.save(regulation);
					} 
				}
			} // end save regulation to database
		}else if(result.get("error").equals("恭喜，没有违章信息")){
			// 不存在违规信息
			// 汽车信息入库
			if (car == null) {
				Car c = new Car();
				c.setCardArea(regulationForm.getArea());
				c.setCardNo(regulationForm.getCardNo());
				c.setCardType(regulationForm.getCardType());
				c.setMachineNo(regulationForm.getMachineNo());
				c.setIsReal(false);
				car = carRepository.save(c);
				log.info("New car : " + car);
			}
		}// 其他error不做处理

		return result;

	}
	
	@Override
	public JSONObject searchDriver(DriverForm driverForm) throws DriverException {
		// 查询驾驶员扣分情况
		// 实时查上海交通违规网，结果解析为json后返回
		JSONObject result = new JSONObject();
		JSONArray items = new JSONArray();
		HttpClient client = HttpClients.createDefault();
		RequestConfig config = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(3000).build();
		HttpPost post = null;
		// 提交查询表单
        post = new HttpPost("http://www.shjtaq.com/zwfg/chafen.asp?id=1");
        post.addHeader("Host", "www.shjtaq.com");
        post.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        post.addHeader("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
        post.addHeader("Accept-Encoding", "gzip, deflate");
        post.addHeader("Referer", "http://www.shjtaq.com/zwfg/chafen.asp");
        post.addHeader("Connection", "keep-alive");
        
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("act", "search"));
        nvps.add(new BasicNameValuePair("licensenums", driverForm.getDriverNo()));
        nvps.add(new BasicNameValuePair("x", "0"));
        nvps.add(new BasicNameValuePair("x", "y"));
        HttpResponse res;
        String resultHTML;
        try {
			post.setEntity(new UrlEncodedFormEntity(nvps, "gb2312"));
			post.setConfig(config);
			res = client.execute(post);
			resultHTML = new String(SearchClient.getStringResult(res.getEntity()).getBytes("ISO-8859-1"), "GB2312");
		} catch (Exception e) {
			DriverException de = new DriverException(DriverException.SearchDriverException, "Search Driver Error: " + e.getMessage(), this.getClass().getName());
			de.setStackTrace(e.getStackTrace());
			throw de;
		}
        post.releaseConnection();
        log.debug(resultHTML);
		
        if(resultHTML.contains("请输入正确的档案编号！")) {
        	result.put("error", "请输入正确的档案编号！");
        } else if(resultHTML.contains("目前没有违法记录！")){
        	result.put("error", "目前没有违法记录！");
        } else {
        	// 有扣分记录，解析内容，返回JSON给移动端
        	Document doc = Jsoup.parse(resultHTML);
    		List<Element> elements = doc.getElementsByClass("chinses1");
    		if(elements.size() == 0){
    			throw new DriverException(DriverException.SearchDriverException, "未知异常", this.getClass().getName());
    		}
    		elements.remove(0);
    		elements.remove(elements.size() - 1);
    		log.debug("扣分记录表单：" + elements.size() + ", 应该是1个");
    		for(Element element : elements) {
    			// 应该只有一个
    			List<Element> list = element.getElementsByTag("td");
    			if(list.size() == 0){
        			throw new DriverException(DriverException.SearchDriverException, "未知异常", this.getClass().getName());
        		}
    			list.remove(0);
    			result.put("driverNo", list.remove(0).text().trim());		// 档案编号
    			result.put("driverName", list.remove(0).text().trim());		// 姓名
    			result.put("sumScore", list.remove(0).text().trim());		// 总共扣分
    			list.remove(0);
    			list.remove(0);
    			list.remove(0);
    			list.remove(0);
    			list.remove(0);
    			list.remove(0);
    			list.remove(list.size() - 1);
    			// 解析具体扣分
    			for(int i = 0; i < list.size(); i ++) {
    				switch(i % 25) {	    
    				case 0:items.add(new JSONObject());break; 	// 序号
    				case 1:break;
    				case 2:items.getJSONObject(i / 25).put("processDept", list.get(i).text().trim());break;	// 处理机关 （机关代码）
    				case 3:break;
    				case 4:items.getJSONObject(i / 25).put("seq", list.get(i).text().trim());break;	// 文书编号
    				case 5:break;
    				case 6:items.getJSONObject(i / 25).put("cardNo", list.get(i).text().trim());break;	// 号牌号码
    				case 7:break;
    				case 8:items.getJSONObject(i / 25).put("cardType", list.get(i).text().trim());break;	// 号牌种类
    				case 9:break;
    				case 10:items.getJSONObject(i / 25).put("name", list.get(i).text().trim());break;	// 姓名
    				case 11:break;
    				case 12:items.getJSONObject(i / 25).put("time", list.get(i).text().trim());break;	// 违法时间
    				case 13:break;
    				case 14:items.getJSONObject(i / 25).put("address", list.get(i).text().trim());break;	// 违法地点
    				case 15:break;
    				case 16:items.getJSONObject(i / 25).put("content", list.get(i).text().trim());break;	// 违法内容
    				case 17:break;
    				case 18:items.getJSONObject(i / 25).put("rule", list.get(i).text().trim());break;	// 违反条款
    				case 19:break;
    				case 20:items.getJSONObject(i / 25).put("punishment", list.get(i).text().trim());break;	// 处罚依据
    				case 21:break;
    				case 22:items.getJSONObject(i / 25).put("penalty", list.get(i).text().trim());break;	// 处罚内容
    				case 23:break;
    				case 24:items.getJSONObject(i / 25).put("score", list.get(i).text().trim());break;	// 记分分值
    				default:break;
    				}
    			}
    		}
    		if(items.size() == 0) {
    			result.put("error", "目前没有违法记录！");
    		} else {
    			result.put("items", items);
    		}
        }
			
		return result;
	}

	@Override
	public JSONObject findRegulations(int pages, int pageSize) throws DriverException {
		JSONObject result = new JSONObject();

		Pageable pageable = new PageRequest(pages, pageSize);
		
		Page<Regulation> regulations = regulationRepository.findAll(pageable);
		
		List<Regulation> results = new ArrayList<Regulation>();
		
		for(Regulation regulation : regulations.getContent()){
			try {
				results.add(regulation.clone());
			} catch (CloneNotSupportedException e) {
				DriverException de = new DriverException(DriverException.RegulationCloneException, "Regulation Clone Error: " + e.getMessage(), this.getClass().getName());
				de.setStackTrace(e.getStackTrace());
				throw de;
			}
		}
		JSONArray arrUploads = JSONArray.fromObject(results, MyJsonUtil.getConfig());
		result.put("results", arrUploads);
		
		return result;
	}
}
